﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO; // for Documentation.xml
using System.Threading; // for Splash
using LogicCircuit;
namespace LogicCircuit
{
              
    public partial class MainForm : Form
    {
        LogicCircuit LogicCircuitApp = new LogicCircuit();

        private Rectangle dragBoxFromMouseDown;
        private int lastMouseDownX, lastMouseDownY;
        private int lastMouseClickX, lastMouseClickY;
        private Point screenOffset;
        private bool moving = false;
        private bool selected = false;
        private string filePath = "";
        
        public MainForm()
        {

            InitializeComponent();
            lbl_status.Text = "";
            lbl_status2.Text = "";
            this.MouseMove += new MouseEventHandler(this.MainForm_MouseMove);
            elementBar.MouseDown += new MouseEventHandler(elementBar_MouseDown);
            elementBar.MouseUp += new MouseEventHandler(elementBar_MouseUp);
            elementBar.MouseMove += new MouseEventHandler(elementBar_MouseMove);
            elementBar.GiveFeedback += new System.Windows.Forms.GiveFeedbackEventHandler(this.elementBar_GiveFeedback);
            elementBar.QueryContinueDrag += new System.Windows.Forms.QueryContinueDragEventHandler(elementBar_QueryContinueDrag);
            
            panel.AllowDrop = true;
            panel.MouseMove += new MouseEventHandler(panel_MouseMove);
            panel.MouseDown += new MouseEventHandler(panel_MouseDown);
            panel.DragOver += new DragEventHandler(panel_DragOver);
            panel.DragDrop += new DragEventHandler(panel_DragDrop);
            panel.DragEnter += new System.Windows.Forms.DragEventHandler(panel_DragEnter);
            panel.DragLeave += new System.EventHandler(panel_DragLeave);
            panel.MouseLeave += new System.EventHandler(panel_MouseLeave);
            panel.QueryContinueDrag += new System.Windows.Forms.QueryContinueDragEventHandler(panel_QueryContinueDrag);
            this.panel.Paint += new System.Windows.Forms.PaintEventHandler(LogicCircuitApp.draw);

        }
        private void elementBar_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            dragBoxFromMouseDown = Rectangle.Empty; 
        }
        private void elementBar_MouseDown(object sender, MouseEventArgs e)
        {
            moving = false;
            lastMouseDownX = e.X;
            lastMouseDownY = e.Y;
        }

        private void elementBar_MouseMove(object sender, MouseEventArgs e)
        {
            if ((e.X >= 10 && e.Y >= 10) && (e.X <= 89 && e.Y <= 69))
                elementBar.Cursor = Cursors.Hand;
            else if ((e.X >= 10 && e.Y >= 76) && (e.X <= 89 && e.Y <= 135))
                elementBar.Cursor = Cursors.Hand;
            else if ((e.X >= 10 && e.Y >= 172) && (e.X <= 89 && e.Y <= 231))
                elementBar.Cursor = Cursors.Hand;
            else if ((e.X >= 10 && e.Y >= 238) && (e.X <= 89 && e.Y <= 297))
                elementBar.Cursor = Cursors.Hand;
            else if ((e.X >= 10 && e.Y >= 308) && (e.X <= 89 && e.Y <= 367))
                elementBar.Cursor = Cursors.Hand;
            else if ((e.X >= 10 && e.Y >= 390) && (e.X <= 89 && e.Y <= 449))
                elementBar.Cursor = Cursors.Hand;
            else
                elementBar.Cursor = Cursors.Default;
            if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
            {
                    try
                    {
                        //MyNormalCursor = new Cursor("3dwarro.cur");
                        //MyNoDropCursor = new Cursor("3dwno.cur");
                    }
                    catch
                    {
                        // An error occurred while attempting to load the cursors, so use
                        // standard cursors.
                        //UseCustomCursorsCheck.Checked = false;
                    }
                    finally
                    {
                        screenOffset = SystemInformation.WorkingArea.Location;              
                        DragDropEffects dropEffect = elementBar.DoDragDrop(elementBar.Capture, DragDropEffects.All | DragDropEffects.Link);
                        if (dropEffect == DragDropEffects.Move)
                        {
                        
                        }
                    }
                }
        }
        private void elementBar_GiveFeedback(object sender, System.Windows.Forms.GiveFeedbackEventArgs e)
        {

        }
        
        private void panel_MouseDown(object sender, MouseEventArgs e)
        {
            // Remember the point where the mouse down occurred. The DragSize indicates
            // the size that the mouse can move before a drag event should be started.                
            Size dragSize = new Size(30, 30);

            // Create a rectangle using the DragSize, with the mouse position being
            // at the center of the rectangle.
            dragBoxFromMouseDown = new Rectangle(new Point(e.X - dragSize.Width / 2,
                                                           e.Y - dragSize.Height / 2), dragSize);
            moving = true;
            lastMouseDownX = e.X;
            lastMouseDownY = e.Y;

        }
        private void panel_MouseMove(object sender, MouseEventArgs e)
        {

            if (selected)
            {
                panel.Refresh();
                Graphics gr = panel.CreateGraphics();
                Pen myPen = new Pen(Color.Purple);
                myPen.Width = 2;
                gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
                gr.DrawLine(myPen, lastMouseClickX, lastMouseClickY, e.X, e.Y);       
            }
            if (LogicCircuitApp.isElement(e.X, e.Y))
            {
                panel.Cursor = Cursors.Hand;
                lbl_status.Text = "Element";
                if (LogicCircuitApp.isInputOutput(e.X, e.Y) != -1)
                    lblFeedback.Text = "Single click to create a connection, double click to remove";
                else
                    lblFeedback.Text = "";
            }
            else
            {
                panel.Cursor = Cursors.Default;
                lbl_status.Text = e.X + "," + e.Y;
            }
            if ((e.Button & MouseButtons.Left) == MouseButtons.Left &&
                dragBoxFromMouseDown != Rectangle.Empty && !dragBoxFromMouseDown.Contains(e.X, e.Y))
            {
                try
                {
                    //MyNormalCursor = new Cursor("3dwarro.cur");
                    //MyNoDropCursor = new Cursor("3dwno.cur");
                }
                catch
                {
                    // An error occurred while attempting to load the cursors, so use
                    // standard cursors.
                    //UseCustomCursorsCheck.Checked = false;
                }
                finally
                {
                    screenOffset = SystemInformation.WorkingArea.Location;
                    DragDropEffects dropEffect = panel.DoDragDrop(panel.Capture, DragDropEffects.All | DragDropEffects.Link);
                    if (dropEffect == DragDropEffects.Move)
                    {

                    }
                }
            }
        }
        private void panel_MouseLeave(object sender, EventArgs e)
        {
            lbl_status.Text = "";
        }
        private void panel_DragOver(object sender, System.Windows.Forms.DragEventArgs e)
        {
            int x, y; 
            Point lastCoords = new Point();
            lastCoords.X = lastMouseDownX;
            lastCoords.Y = lastMouseDownY;
            lastCoords = panel.PointToScreen(lastCoords);
            Point screenCoords = Cursor.Position;

            Point controlRelatedCoords = this.panel.PointToClient(screenCoords);
            x = controlRelatedCoords.X;
            y = controlRelatedCoords.Y;
            if (moving)
            {
                if (LogicCircuitApp.moveElement(lastMouseDownX, lastMouseDownY, x - 39, y - 29))
                {
                    lblFeedback.Text = "Moving Element";
                    lastMouseDownX = x;
                    lastMouseDownY = y;
                   
                }
                else
                {
                    Cursor.Position = lastCoords;
                    lblFeedback.Text = "";
                }

            }
            else
            {
                    
            }
            RefreshPanel();
            e.Effect = DragDropEffects.Move;       
        }
        private void panel_DragDrop(object sender, System.Windows.Forms.DragEventArgs e) 
        {
            int x, y;
            Point screenCoords = Cursor.Position;
            Point controlRelatedCoords = this.panel.PointToClient(screenCoords);
            x = controlRelatedCoords.X;
            y = controlRelatedCoords.Y;

            // Perform drag-and-drop, depending upon the effect.
            if (e.Effect == DragDropEffects.Copy || e.Effect == DragDropEffects.Move)
            {
                string type;
                if (!moving)
                {
                    if ((lastMouseDownX >= 10 && lastMouseDownY >= 10) && (lastMouseDownX <= 89 && lastMouseDownY <= 69))
                        type = "Source0";
                    else if ((lastMouseDownX >= 10 && lastMouseDownY >= 76) && (lastMouseDownX <= 89 && lastMouseDownY <= 135))
                        type = "Source1";
                    else if ((lastMouseDownX >= 10 && lastMouseDownY >= 172) && (lastMouseDownX <= 89 && lastMouseDownY <= 231))
                        type = "And";
                    else if ((lastMouseDownX >= 10 && lastMouseDownY >= 238) && (lastMouseDownX <= 89 && lastMouseDownY <= 297))
                        type = "Or";
                    else if ((lastMouseDownX >= 10 && lastMouseDownY >= 308) && (lastMouseDownX <= 89 && lastMouseDownY <= 367))
                        type = "Not";
                    else if ((lastMouseDownX >= 10 && lastMouseDownY >= 390) && (lastMouseDownX <= 89 && lastMouseDownY <= 449))
                        type = "Sink";
                    else
                        type = "";
                    // If there is element already
                    
                   LogicCircuitApp.addElement(x - 39, y - 29, type);
                   RefreshPanel();
                }
                else
                {
                    moving = false;
                }
            }
            selected = false;
            if (selected)
                lbl_status2.Text = "Selected";
            else
                lbl_status2.Text = "Not Selected";
        }

        private void elementBar_QueryContinueDrag(object sender, System.Windows.Forms.QueryContinueDragEventArgs e)
        {
            // Cancel the drag if the mouse moves off the form.
            PictureBox pb = sender as PictureBox;
            
            if (pb != null)
            {

                Form f = pb.FindForm();

                // Cancel the drag if the mouse moves off the form. The screenOffset
                // takes into account any desktop bands that may be at the top or left
                // side of the screen.
                if (((Control.MousePosition.X - screenOffset.X) < f.DesktopBounds.Left) ||
                    ((Control.MousePosition.X - screenOffset.X) > f.DesktopBounds.Right) ||
                    ((Control.MousePosition.Y - screenOffset.Y) < f.DesktopBounds.Top) ||
                    ((Control.MousePosition.Y - screenOffset.Y) > f.DesktopBounds.Bottom))
                {

                    e.Action = DragAction.Cancel;
                }
            }
        }
        private void panel_DragEnter(object sender, System.Windows.Forms.DragEventArgs e)
        {

        }
        private void panel_DragLeave(object sender, System.EventArgs e)
        {
            lbl_status.Text = "";
        }
        private void panel_QueryContinueDrag(object sender, System.Windows.Forms.QueryContinueDragEventArgs e)
        {
            // Cancel the drag if the mouse moves off the form.
            PictureBox pb = sender as PictureBox;
            if (pb != null)
            {

                Form f = pb.FindForm();

                // Cancel the drag if the mouse moves off the form. The screenOffset
                // takes into account any desktop bands that may be at the top or left
                // side of the screen.
                if (((Control.MousePosition.X - screenOffset.X) < f.DesktopBounds.Left) ||
                    ((Control.MousePosition.X - screenOffset.X) > f.DesktopBounds.Right) ||
                    ((Control.MousePosition.Y - screenOffset.Y) < f.DesktopBounds.Top) ||
                    ((Control.MousePosition.Y - screenOffset.Y) > f.DesktopBounds.Bottom))
                {

                    e.Action = DragAction.Cancel;
                }
            }
        }
        private void MainForm_MouseMove(object sender, MouseEventArgs e)
        {
        }
        private void RefreshPanel()
        {
            panel.Refresh();
            LogicCircuitApp.draw(panel);
            if (selected)
                lbl_status2.Text = "Selected";
            else
                lbl_status2.Text = "Not Selected";
        }

        private void MainForm_Move(object sender, EventArgs e)
        {
            RefreshPanel();
        }

        private void MainForm_Shown(object sender, EventArgs e)
        {
            RefreshPanel();
        }

        private void MainForm_SizeChanged(object sender, EventArgs e)
        {
            RefreshPanel();
        }

        private void panel_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (LogicCircuitApp.isElement(e.X, e.Y))
            {
                if (LogicCircuitApp.isInputOutput(e.X, e.Y) != -1)
                {
                    LogicCircuitApp.removeConnex(e.X, e.Y);
                    RefreshPanel();
                    selected = false;
                }
            }
            else
            {
                selected = false;
            }
            if (selected)
                lbl_status2.Text = "Selected";
            else
                lbl_status2.Text = "Not Selected";
          }

        private void panel_MouseClick(object sender, MouseEventArgs e)
        {
            
            lblFeedback.Text = "";

            int result = LogicCircuitApp.isInputOutput(e.X, e.Y);
            if (result != -1)
            {
                if (selected)
                {
                    if (result == 1)
                    {
                        if (LogicCircuitApp.addConnex(lastMouseClickX, lastMouseClickY, e.X, e.Y))
                        {
                        }
                    }
                    else
                    {
                        if (LogicCircuitApp.addConnex( e.X,  e.Y, lastMouseClickX, lastMouseClickY))
                        {
                        }
                    }
                    selected = false;
                    
                }
                else
                {
                    selected = true;
                }
                lastMouseClickX = e.X;
                lastMouseClickY = e.Y;
            }
            else
            {
                selected = false;
            }
            if (selected)
                lbl_status2.Text = "Selected";
            else
                lbl_status2.Text = "Not Selected";
            RefreshPanel();
        }

        /*	`Main Menu and toolbar buttons tied in the same event
        --------------------------------------------------------------*/

        private void mnuNew_Click(object sender, EventArgs e)
        {
            saveChangesFirst("new");
        }

        private void saveChangesFirst(string reason)
        {
            DialogResult result = MessageBox.Show("Do you want to save changes?", "ESARL Logic Circuit " + reason, MessageBoxButtons.YesNoCancel);

            if (result == DialogResult.Yes || result == DialogResult.No)
            {
                if (result == DialogResult.Yes)
                    initiateSave();

                if (reason == "new")
                    restart();
                else if (reason == "load")
                    initiateLoad();
                else if (reason == "quit")
                    this.Close();
                reason = "";
            }
            else
            { // implement clos change global variable of close to false
            }
        }

        private void mnuLoad_Click(object sender, EventArgs e)
        {
            saveChangesFirst("load");
        }

        private void mnuSave_Click(object sender, EventArgs e)
        {
            initiateSave();
        }

        private void mnuSaveAs_Click(object sender, EventArgs e)
        {
            initiateSaveAs();
        }

        private void initiateLoad()
        {
            openFileDialog1.DefaultExt = ".lcd"; // Default file extension
            openFileDialog1.Filter = "LCD documents (.lcd)|*.lcd"; // LogicCircuit files by extens
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                filePath = openFileDialog1.FileName;
                if (LogicCircuitApp.loadFile(filePath))
                {
                    RefreshPanel();
                    lblFeedback.Text = "File: \"" + openFileDialog1.FileName + "\"  was successfully loaded!";
                }
            }
        }

        private void initiateSave()
        {
            saveFileDialog1.DefaultExt = ".lcd"; // Default file extension
            saveFileDialog1.Filter = "LCD documents (.lcd)|*.lcd"; // LogicCircuit files by extens

            if (filePath == "")
            {
                if (saveFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    filePath = saveFileDialog1.FileName;
                    LogicCircuitApp.saveFile(filePath);
                    lblFeedback.Text = "File: \"" + openFileDialog1.FileName + "\"  was successfully saved!";
                }
            }
            else
            {
                LogicCircuitApp.saveFile(filePath);
                lblFeedback.Text = "File: \"" + openFileDialog1.FileName + "\"  was successfully saved!";
            }
        }
        private void initiateSaveAs()
        {
            saveFileDialog1.DefaultExt = ".lcd"; // Default file extension
            saveFileDialog1.Filter = "LCD documents (.lcd)|*.lcd"; // LogicCircuit files by extens       

            if (saveFileDialog1.ShowDialog() == DialogResult.OK)
            {
                filePath = saveFileDialog1.FileName;
                LogicCircuitApp.saveFile(filePath);
                lblFeedback.Text = "File: \"" + saveFileDialog1.FileName + "\"  was successfully saved!";
            }
        }

        private void restart()
        {
            LogicCircuitApp.clearAll();
            RefreshPanel();
            filePath = "";
        }

        private void mnuQuit_Click(object sender, EventArgs e)
        {
            saveChangesFirst("quit");
        }
        /* Edit Submenus */
        private void mnuClearPanel_Click(object sender, EventArgs e)
        {
            LogicCircuitApp.clearAll();
            RefreshPanel();
        }

        private void mnuDeleteElement_Click(object sender, EventArgs e)
        {
            if (LogicCircuitApp.isElement(lastMouseDownX, lastMouseDownY))
                LogicCircuitApp.removeElement(lastMouseDownX, lastMouseDownY);
            RefreshPanel();
        }

        private void mnuToggleSource_Click(object sender, EventArgs e)
        {
            if (LogicCircuitApp.isElement(lastMouseDownX, lastMouseDownY))
                LogicCircuitApp.toggleSource(lastMouseDownX, lastMouseDownY);
            RefreshPanel();
        }

        /*	`The following 2 methods Can(should) be implemented in LogicCircuit class 
        --------------------------------------------------------------*/
        private void mnuDoc_Click(object sender, EventArgs e)  
        {
            string holder = Path.GetDirectoryName(Application.ExecutablePath);
            System.Diagnostics.Process.Start("IEXPLORE.EXE", holder + "\\LogicCircuit.XML");
            
            System.Diagnostics.Process.Start("IEXPLORE.EXE", holder + "\\ESARL_LogicCircuit.pdf");
        }

        private void mnuAbout_Click(object sender, EventArgs e)
        {
            Form about = new AboutForm();
            about.Show();
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            //e.Cancel = true;
            //saveChangesFirst("quit");
        }

        private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            //e.Cancel = true;
            //saveChangesFirst("quit");
        }

    }
}
